using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using UnityEngine;

public class CarAIController : MonoBehaviour
{
    // 车辆轮子的变换
    [Header("轮子")]
    public Transform frontRight;       // 右前轮的变换
    public Transform frontLeft;        // 左前轮的变换
    public Transform rearRight;        // 右后轮的变换
    public Transform rearLeft;         // 左后轮的变换

    // 车辆轮子碰撞体
    public WheelCollider frontRightCollider;  // 右前轮的轮子碰撞体
    public WheelCollider frontLeftCollider;   // 左前轮的轮子碰撞体
    public WheelCollider rearRightCollider;   // 右后轮的轮子碰撞体
    public WheelCollider rearLeftCollider;    // 左后轮的轮子碰撞体

    [Header("路线设置")]
    [Tooltip("如果为真，汽车到达终点时将无限循环该路线。")]
    public bool loopRoute = false;

    [Header("检查点和检测")]
    // 检查点
    [Tooltip("AI将寻找的检查点变换。每当车辆进入检查点时，此变量会更改为下一个连接的检查点，或者如果存在多个检查点，则随机选择一个。")]
    public Transform nextCheckpoint;  // 下一个检查点的变换
    [Tooltip("AI将从这些位置发射射线以检测物体。将它们放置在车辆碰撞体内部是理想的。")]
    public List<Transform> checks = new List<Transform> { null };  // 检测点列表
    [Tooltip("如果为true，AI将检查检查点。")]
    public bool CheckPointSearch = true;  // 是否检查检查点
    [Tooltip("如果为true，表示车辆前方有物体。")]
    public bool objectDetected = false;   // 是否检测到前方物体
    [Tooltip("如果为true，车辆将由AI控制。")]
    public bool isCarControlledByAI = true;  // 是否由AI控制车辆
    [Tooltip("车辆可见的图层。如果取消勾选某个图层，车辆将不会对来自该图层的物体做出反应。")]
    public LayerMask seenLayers = Physics.AllLayers;  // 车辆可见的图层

    [Header("车辆设置")]

    // 速度设置
    [Tooltip("车辆速度，单位为公里/小时。此值仅供读取，修改它不会影响车辆的实际速度。")]
    public int kmh;  // 车辆速度（公里/小时）
    [Tooltip("AI将遵守的速度限制，单位为公里/小时。")]
    public int speedLimit;  // 速度限制
    [Tooltip("与其他物体保持的距离。")]
    public float distanceFromObjects = 2f;  // 与其他物体保持的距离
    [Tooltip("车辆超出或低于速度限制的数值。例如：0=遵守速度限制，10=超过速度限制10公里/小时，-10=低于速度限制10公里/小时。")]
    public int recklessnessThreshold = 0;  // 超速或减速阈值
    [Tooltip("如果为true，车辆在Z轴翻转时将被销毁。")]
    public bool despawnForFlippingOver = true;  // 是否在翻转时销毁车辆
    [Tooltip("如果为true，车辆将切换到出租车模式，意味着它将从起点检查点行驶到终点检查点。这些检查点需要在检查点网络中连接。")]
    public bool taxiMode = false;  // 是否启用出租车模式

    // 车辆参数
    [Tooltip("加速阈值。")]
    public float acceleration = 100f;  // 加速阈值
    [Tooltip("刹车阈值。提示：使其大于加速阈值，以便车辆可以更快地刹车。")]
    public float breaking = 1000f;  // 刹车阈值

    // 私有变量
    private Stopwatch stopwatch = new Stopwatch();  // 用于计算速度的计时器
    private Vector3 lastPos;  // 上一个位置
    private float steerAngle = 0f;  // 转向角度
    private bool flipOverCheck = false;  // 翻转检测标志

    private void FixedUpdate()
    {
        // 更新轮子位置和旋转
        WheelUpdate(frontRight, frontRightCollider);
        WheelUpdate(frontLeft, frontLeftCollider);
        WheelUpdate(rearRight, rearRightCollider);
        WheelUpdate(rearLeft, rearLeftCollider);

        // 计算速度
        CalculateKMH();

        // 搜索功能点
        SearchForCheckpoints();

        // 检查车辆是否翻转
        if (despawnForFlippingOver && !flipOverCheck)
        {
            flipOverCheck = true;
            StartCoroutine(CheckForFlippingOver());
        }
    }

    // 检查车辆是否翻转的协程
    IEnumerator CheckForFlippingOver()
    {
        bool deleteCar = isCarFlipedOver();  // 检查车辆是否翻转

        if (deleteCar)
        {
            for (int i = 0; i < 10; i++)
            {
                if (!isCarFlipedOver())
                {
                    deleteCar = false;
                }
                yield return new WaitForSeconds(1);
            }

            if (deleteCar)
            {
                UnityEngine.Debug.Log("车辆 " + gameObject.name + " 因翻转而销毁。");
                Destroy(gameObject);  // 销毁车辆
            }
        }

        yield return new WaitForSeconds(10);
        flipOverCheck = false;  // 重置翻转检测标志
        yield return null;
    }

    // 检查车辆是否翻转
    private bool isCarFlipedOver()
    {
        if (transform.rotation.eulerAngles.z > 30f || transform.rotation.eulerAngles.z < -30f)
        {
            return true;  // 如果Z轴旋转角度超过30度，认为车辆翻转
        }
        return false;
    }

    // 更新轮子位置和旋转
    private void WheelUpdate(Transform transform, WheelCollider collider)
    {
        Vector3 pos;
        Quaternion rot;
        collider.GetWorldPose(out pos, out rot);  // 获取轮子的世界位置和旋转
        transform.position = pos;  // 更新轮子位置
        transform.rotation = rot;  // 更新轮子旋转
    }

    /// <summary>
    /// 根据给定的值加速车辆。
    /// </summary>
    public void Accelerate(float value)
    {
        frontRightCollider.motorTorque = value;  // 设置右前轮的电机扭矩
        frontLeftCollider.motorTorque = value;   // 设置左前轮的电机扭矩
    }

    /// <summary>
    /// 根据给定的值刹车车辆。
    /// </summary>
    public void Break(float value)
    {
        frontRightCollider.brakeTorque = value;  // 设置右前轮的刹车扭矩
        frontLeftCollider.brakeTorque = value;   // 设置左前轮的刹车扭矩
        rearRightCollider.brakeTorque = value;   // 设置右后轮的刹车扭矩
        rearLeftCollider.brakeTorque = value;    // 设置左后轮的刹车扭矩
    }

    /// <summary>
    /// 根据给定的角度转动前轮。
    /// </summary>
    public void Turn(float angle)
    {
        frontRightCollider.steerAngle = angle;  // 设置右前轮的转向角度
        frontLeftCollider.steerAngle = angle;   // 设置左前轮的转向角度
    }

    // 计算车辆速度（公里/小时）
    private void CalculateKMH()
    {
        if (stopwatch.IsRunning)
        {
            stopwatch.Stop();  // 停止计时器

            float distance = (transform.position - lastPos).magnitude;  // 计算位移
            float time = stopwatch.Elapsed.Milliseconds / (float)1000;  // 计算时间（秒）

            kmh = (int)(3600 * distance / time / 1000);  // 计算速度（公里/小时）

            lastPos = transform.position;  // 更新上一个位置
            stopwatch.Reset();  // 重置计时器
            stopwatch.Start();  // 启动计时器
        }
        else
        {
            lastPos = transform.position;  // 更新上一个位置
            stopwatch.Reset();  // 重置计时器
            stopwatch.Start();  // 启动计时器
        }
    }

    /// <summary>
    /// 设置车辆速度。
    /// </summary>
    public void SetSpeed(int speedLimit)
    {
        if (kmh > speedLimit)
        {
            Break(breaking);  // 如果速度超过限制，刹车
            Accelerate(0);    // 停止加速
        }
        else if (kmh < speedLimit)
        {
            Accelerate(acceleration);  // 如果速度低于限制，加速
            Break(0);                  // 停止刹车
        }
    }

    // 搜索结果点
    private void SearchForCheckpoints()
    {
        if (CheckPointSearch && isCarControlledByAI)
        {
            // 计算下一个检查点的相对位置
            if (nextCheckpoint == null)
            {
                // 如果循环模式启用，重置到初始检查点
                if (loopRoute)
                {
                    Transform initialCheckpoint = GetComponent<TaxiScript>().startCheckpoint;
                    if (initialCheckpoint != null)
                    {
                        nextCheckpoint = initialCheckpoint;
                    }
                }
                else
                {
                    // 如果不是循环模式，停止车辆
                    SetSpeed(0);
                    return;
                }
            }

            Vector3 nextCheckpointRelative = transform.InverseTransformPoint(nextCheckpoint.position);

            // 计算转向角度
            steerAngle = nextCheckpointRelative.x / nextCheckpointRelative.magnitude;
            float xangle = nextCheckpointRelative.y / nextCheckpointRelative.magnitude;

            steerAngle = Mathf.Asin(steerAngle) * 180f / 3.14f;  // 转换为角度
            xangle = Mathf.Asin(xangle) * 180f / 3.14f;          // 转换为角度

            Turn(steerAngle);  // 转向

            // 计算最大检测距离
            float maxDistance = kmh * kmh / 100f + distanceFromObjects;

            RaycastHit carHit = new RaycastHit();  // 射线检测结果
            int objectInFront = 0;  // 前方物体计数

            // 遍历检测点
            for (int i = 0; i < checks.Count; i++)
            {
                // 设置检测点的旋转
                checks[i].localRotation = Quaternion.Euler(-xangle, steerAngle, 0);
                // 射线检测前方物体
                bool isObjectInFront = Physics.Raycast(
                    checks[i].position, 
                    checks[i].forward, 
                    out carHit, 
                    maxDistance, 
                    seenLayers, 
                    QueryTriggerInteraction.Ignore
                );

                #if UNITY_EDITOR
                // 在编辑器中绘制射线（调试用）
                UnityEngine.Debug.DrawRay(checks[i].position, checks[i].forward * maxDistance, Color.green);
                #endif

                if (isObjectInFront)
                    objectInFront++;  // 增加前方物体计数
            }

            // 如果检测到前方有物体
            if (objectInFront > 0)
            {
                SetSpeed(0);  // 设置速度为0
                objectDetected = true;  // 标记为检测到物体
            }
            else
            {
                objectDetected = false;  // 标记为未检测到物体
                int speed = speedLimit + recklessnessThreshold;  // 计算目标速度
                if (speedLimit == 0)
                {
                    speed = 0;  // 如果速度限制为0，目标速度也为0
                }
                if (speed == 0)
                {
                    speed = speedLimit;  // 如果目标速度为0，使用速度限制
                }
                SetSpeed(speed);  // 设置目标速度
            }
        }
    }
}